package com.jrx.anytxn.atom.job.custBatch.step;

import com.jrx.anytxn.atom.bean.CustBatchSaveBean;
import com.jrx.anytxn.atom.service.IDealCustBatchService;
import com.jrx.anytxn.common.data.TxnRespCode;
import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.customer.constant.CustomerConstant;
import com.jrx.anytxn.customer.entity.CmCustomerFirstLevel;
import com.jrx.anytxn.customer.mapper.ext.ExtCmCustomerFirstLevelMapper;
import com.jrx.anytxn.param.entity.PrOrganizationTable;
import com.jrx.anytxn.param.service.system.IOrganizationTableService;
import com.jrx.anytxn.redisson.service.RedissonLockService;
import com.jrx.anytxn.redisson.util.LockType;
import com.jrx.anytxn.transaction.constant.TransBizConstant;
import com.jrx.anytxn.transaction.constant.TransErrMsgConstant;
import org.mybatis.spring.SqlSessionTemplate;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
public class CustBatchProcessor implements ItemProcessor<CmCustomerFirstLevel, CustBatchSaveBean> {

    Logger logger = LoggerFactory.getLogger(CustBatchProcessor.class);
    @Autowired
    private IDealCustBatchService dealCustBatchService;
    @Autowired
    private RedissonLockService redissonLockService;
    @Autowired
    private IOrganizationTableService organizationTableService;
    @Resource
    private ExtCmCustomerFirstLevelMapper extCmCustomerFirstLevelMapper;
    @Resource(name = "bizSqlSessionTemplate")
    private SqlSessionTemplate sqlSessionTemplate;

    @Override
    public CustBatchSaveBean process(CmCustomerFirstLevel firstLevel) throws Exception {
        String customerId = firstLevel.getCustomerId();
        String lockKey = String.format(TransBizConstant.CUST_BATCH_REDIS_LOCK, firstLevel.getTenantId(), customerId);
        PrOrganizationTable org = organizationTableService.findByOrgIdForBatch(firstLevel.getOrganizationId());
        Date nextProcessingDate = org.getNextProcessingDate();
        logger.info("RedissionLock key:{}", lockKey);
        RLock lock = redissonLockService.getRLock(lockKey, LockType.REENTRANT_LOCK);
        try {
            boolean lockFlag = lock.tryLock(CustomerConstant.LOAN_REDIS_LOCK_WAITE_TIME, CustomerConstant.LOAN_REDIS_LOCK_LESS_TIME, TimeUnit.SECONDS);
            if (!lockFlag) {
                String msg = String.format(TransErrMsgConstant.GET_REDIS_LOCK_ERROR, lockKey);
                throw new TxnBizException(TxnRespCode.ERROR.getCode(), msg);
            }
            logger.info("获取到RedissionLock key:{}", lockKey);

            //防止联机交易在reader后 processor执行之前更新一级档
            sqlSessionTemplate.clearCache();
            firstLevel = extCmCustomerFirstLevelMapper.selectFirstLevelByOrgIdAndCusId(firstLevel.getCustomerId(),firstLevel.getOrganizationId(),firstLevel.getTenantId());
            logger.info("调用客户原子服务进行日终账户处理开始:tenantId->{},客户id->{},orgBusDate->{},custDate->{}",
                    firstLevel.getTenantId(),customerId,org.getNextProcessingDate(),firstLevel.getNextProcessingDate());
            if (!nextProcessingDate.equals(firstLevel.getNextProcessingDate())) {
                return dealCustBatchService.dealCustBatch(firstLevel);
            } else {
                return dealCustBatchService.dealAlreadyCustBatch(firstLevel);
            }
        } catch (Exception e) {
            logger.error("异常信息:", e);
            if(lock.isLocked()) {
                if(lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
            throw e;
        }
    }
}
